package main;

import br.cin.stadium.middleware.directory.ServerLocation;
import br.cin.stadium.middleware.marshall.Marshaller;
import br.cin.stadium.middleware.network.config.NetConfig;
import br.cin.stadium.middleware.util.Logger;

public class StadiumDirectoryService {

	private static StadiumDirectoryService service = null;
	private RegisterBroker registerBroker = null;
	private ResponseBroker responseBroker = null;
	private StadiumDirectoryServer server = null;

	public static final byte BIND_CODE   = 1;
	public static final byte UNBIND_CODE = 2;
	
	private StadiumDirectoryService() {
		this.registerBroker = new RegisterBroker();
		this.responseBroker = new ResponseBroker();
		this.server = new StadiumDirectoryServer();
	}

	public static StadiumDirectoryService getInstance() {
		if (service == null) {
			service = new StadiumDirectoryService();
		}
		return service;
	}

	public void init() {
		Runnable r1 = new Runnable() {
			public void run() {
				while (true) {
					registerBroker.listen();
					Logger.log("StadiumDirectoryService", "run-thread_1", "New connection !!!");

					byte[] bytes = registerBroker.getRequest();

					byte code = bytes[0];
					byte[] data = new byte[bytes.length-1];
					System.arraycopy(bytes, 1, data, 0, bytes.length-1);
					
					try {
						
						if (code == BIND_CODE) {
							Logger.log("CODE = BIND");
							ServerLocation sl = new ServerLocation();
							Marshaller.unmarshall(sl, data);
							server.register(sl);

						} else if (code == UNBIND_CODE) {
							Logger.log("CODE = UN_BIND");

							ServerLocation sl = new ServerLocation();
							Marshaller.unmarshall(sl, data);
							server.unRegister(sl);

						} else {
							System.err.println("Code " + code + " not recognized.");
						}
					} catch (Exception e) {
						System.err.println(e.getMessage());
					} finally {
						registerBroker.close();
					}
				}
			}
		};

		new Thread(r1).start();

		Runnable r2 = new Runnable() {
			public void run() {
				while (true) {
					responseBroker.listen();
					responseBroker.response(Marshaller.marshall(server.getServers()));
					responseBroker.close();
				}
			}
		};

		new Thread(r2).start();
	}

	public static void main(String[] args) {
		if (args.length == 2) {
			NetConfig.STADIUM_DIRECTOR_PORT_REGISTER = Integer.parseInt(args[0]);
			NetConfig.STADIUM_DIRECTOR_PORT_RETRIEVE = Integer.parseInt(args[1]);
		}
		StadiumDirectoryService service = StadiumDirectoryService.getInstance();
		service.init();
		System.out.println("Service running.");
	}
}